package com.hhs.storage.config;

import com.alibaba.fastjson.JSON;
import com.hhs.storage.bean.ResponseInfo;
import org.apache.tomcat.util.http.fileupload.FileUploadBase;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;

/**
 * @Auther: shadow
 * @Date: 2018/9/29 16:04
 * @Description:
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    public static final String DEFAULT_ERROR_VIEW = "error";
    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Exception e,
                                            HandlerMethod method) throws Exception {
        ModelAndView mav = null;
        boolean isApi = method != null && (method.hasMethodAnnotation(ResponseBody.class)
                || method.getBeanType().isAnnotationPresent(RestController.class));
        //如果是ajax调用，则返回json串
        if (isApi)
        {
            e.printStackTrace();
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            if(e instanceof DataIntegrityViolationException){
                String msg = e.getMessage();
                //删除时有外键关联
                if(msg.indexOf("foreign key")>0){
                    writer.write(JSON.toJSONString(ResponseInfo.error(e.getMessage())));
//                    writer.write(JSON.toJSONString(ResponseInfo.error("该数据已被关联，不可删除")));
                }else {
                    writer.write(JSON.toJSONString(ResponseInfo.error(e.getMessage())));
                }
            }else{
                writer.write(JSON.toJSONString(ResponseInfo.error(e.getMessage())));
            }
            writer.flush();
        }
        else
        {//form表单，则返回页面
            e.printStackTrace();
            mav = new ModelAndView();
            mav.addObject("exception", "未知异常");
            mav.addObject("url", request.getRequestURL());
            mav.setViewName(DEFAULT_ERROR_VIEW);
        }
        return mav;
    }
    //用于文件上传超过大小的异常提醒

    @Value("${spring.servlet.multipart.max-file-size}")
    String SingleMax;
    @ExceptionHandler(value = MultipartException.class)
    public
    ModelAndView handleBusinessException(MaxUploadSizeExceededException ex, HttpServletResponse response) throws IOException {
        String msg = "上传文件失败";
        if (ex.getCause().getCause() instanceof FileSizeLimitExceededException) {
            msg = "上传文件过大[单文件大小不得超过"+SingleMax+"]";
        } else if (ex.getCause().getCause() instanceof SizeLimitExceededException) {
//            msg = "上传文件过大[总上传文件大小不得超过10M]";
            msg = "上传文件过大";
        }
        ModelAndView mav = null;
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(JSON.toJSONString(ResponseInfo.error(msg)));
        writer.flush();
        return mav;

    }
    //用于bean 的参数验证，验证的参数对象要打上注解 @Validated  详见user的新增
    @ExceptionHandler(value = BindException.class)
    public void bindException(HttpServletRequest request, HttpServletResponse response, BindException exception) throws Exception {

        BindingResult result = exception.getBindingResult();
        Map<String, Object> maps;
        String resultStr="";
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            maps = new HashMap<>(fieldErrors.size());
            fieldErrors.forEach(error -> {
                maps.put(error.getField(), error.getDefaultMessage());
            });
        } else {
            maps = Collections.EMPTY_MAP;
        }

        Iterator keys = maps.keySet().iterator();
        while(keys.hasNext()) {
            String key = (String) keys.next();
            String value= (String) maps.get(key);
            resultStr+=value;
        }
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write(JSON.toJSONString(ResponseInfo.error(resultStr)));
        writer.flush();

    }
}
